//
//  Chapter2ViewController.m
//  OpenGLES_Learning
//
//  Created by Mac Center on 7/26/13.
//  Copyright (c) 2013 Mac Center. All rights reserved.
//

#import "Chapter3ViewController.h"
#import "AGLKVertexAttribArrayBuffer.h"
#import "AGLKContext.h"
#import "AGLKTextureLoader.h"

typedef struct {
    GLKVector3  positionCoords;
    GLKVector3  positionCoords2;
    GLKVector2  textureCoords;
}sceneVertex;

static sceneVertex vertexs[] = {
    {{-0.5, -0.5, 0},{0.0, -0.5, 0}, {0.0f, 0.0f}},
    {{0.5, -0.5, 0},{-0.5, 0.0, 0}, {1.0f, 0.0f}},
    {{-0.5, 0.5, 0},{0.0, 0.0, 0}, {0.0f, 1.0f}}
//    ,    {{0, 0, 0}, {1.0f, 1.0f}}
};

/////////////////////////////////////////////////////////////////
// Define defualt vertex data to reset vertexs when needed
static const sceneVertex defaultvertexs[] =
{
    {{-0.5f, -0.5f, 0.0f},{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f}},
    {{ 0.5f, -0.5f, 0.0f},{ 0.5f, -0.5f, 0.0f}, {1.0f, 0.0f}},
    {{-0.5f,  0.5f, 0.0f},{-0.5f,  0.5f, 0.0f}, {0.0f, 1.0f}}
//    ,    {{0, 0, 0}, {1.0f, 1.0f}}    
};

/////////////////////////////////////////////////////////////////
// Provide storage for the vectors that control the direction
// and distance that each vertex moves per update when animated
static GLKVector3 movementVectors[3] = {
    {-0.02f,  -0.01f, 0.0f},
    {0.01f,  -0.005f, 0.0f},
    {-0.01f,   0.01f, 0.0f}
//    ,    {-0.01f,   0.01f, 0.0f}
};

@interface GLKEffectPropertyTexture (AGLKAdditions)

- (void)aglkSetParameter:(GLenum)parameterID
                   value:(GLint)value;

@end

@implementation GLKEffectPropertyTexture (AGLKAdditions)

- (void)aglkSetParameter:(GLenum)parameterID
                   value:(GLint)value;
{
    glBindTexture(self.target, self.name);
    
    glTexParameteri(
                    self.target,
                    parameterID, 
                    value);
}

@end

@interface Chapter3ViewController ()

@end

@implementation Chapter3ViewController
@synthesize baseEffect;
@synthesize vertexBuffer;
@synthesize textureInfo0;

@synthesize shouldUseLinearFilter;
@synthesize shouldAnimate;
@synthesize shouldRepeatTexture;
@synthesize sCoordinateOffset;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    GLKView    *glView = (GLKView*)self.view;
    NSAssert([glView isKindOfClass:[GLKView class]], @"View controller's view is not a GLKView" );
    
    glView.context = [[AGLKContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    [AGLKContext setCurrentContext:glView.context];
        
    self.baseEffect = [[GLKBaseEffect alloc] init];
    self.baseEffect.useConstantColor =  GL_TRUE;
    self.baseEffect.constantColor = GLKVector4Make(1.0, 1.0, 1.0, 1.0);
    
    // Set the background color stored in the current context
    ((AGLKContext *)glView.context).clearColor = GLKVector4Make(
                                                                0.0f, // Red
                                                                0.0f, // Green
                                                                0.0f, // Blue
                                                                1.0f);// Alpha

    // Create vertex buffer containing vertexs to draw
    self.vertexBuffer = [[AGLKVertexAttribArrayBuffer alloc] initWithAttribStride:sizeof(sceneVertex) numberOfVertices:sizeof(vertexs) / sizeof(sceneVertex) data:vertexs usage:GL_STATIC_DRAW];
    
    //texture 0
    CGImageRef  imageRef = [UIImage imageNamed:@"leaves.gif"].CGImage;
//    GLKTextureInfo  *textureInfo = [GLKTextureLoader textureWithCGImage:imageRef options:nil error:NULL];
//    AGLKTextureInfo *textureInfo = [AGLKTextureLoader textureWithCGImage:imageRef options:nil error:NULL];
    textureInfo0 = [GLKTextureLoader textureWithCGImage:imageRef
                                                options:[NSDictionary dictionaryWithObjectsAndKeys:
                                                         [NSNumber numberWithBool:YES],
                                                         GLKTextureLoaderOriginBottomLeft, nil] error:NULL];
    
//    self.baseEffect.texture2d0.name = textureInfo.name;
//    self.baseEffect.texture2d0.target = textureInfo.target;

    //texture 1
    CGImageRef  imageRef1 = [UIImage imageNamed:@"Tree.png"].CGImage;
    textureInfo1 = [GLKTextureLoader textureWithCGImage:imageRef1
                                                options:[NSDictionary dictionaryWithObjectsAndKeys:
                                                         [NSNumber numberWithBool:YES],
                                                         GLKTextureLoaderOriginBottomLeft, nil] error:NULL];
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    

//    self.baseEffect.texture2d1.name = textureInfo1.name;
//    self.baseEffect.texture2d1.target = textureInfo1.target;
    
}

- (void)viewDidUnload {
    [super viewDidUnload];
    
    GLKView *v = (GLKView *)self.view;
    [EAGLContext setCurrentContext:v.context];
    
    if (vertextBufferID != 0) {
        glDeleteBuffers(1, &vertextBufferID);
        vertextBufferID = 0;
    }
    v.context = nil;
    [AGLKContext setCurrentContext:nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


/////////////////////////////////////////////////////////////////
// Update the current OpenGL ES context texture wrapping mode
- (void)updateTextureParameters
{
    [self.baseEffect.texture2d0
     aglkSetParameter:GL_TEXTURE_WRAP_S
     value:(self.shouldRepeatTexture ?
            GL_REPEAT : GL_CLAMP_TO_EDGE)];
    
    [self.baseEffect.texture2d0
     aglkSetParameter:GL_TEXTURE_MAG_FILTER
     value:(self.shouldUseLinearFilter ?
            GL_LINEAR : GL_NEAREST)];
}


/////////////////////////////////////////////////////////////////
// Update the positions of vertex data to create a bouncing
// animation
- (void)updateAnimatedVertexPositions
{
    if(self.shouldAnimate)
    {  // Animate the triangles vertex positions
        int    i;  // by convention, 'i' is current vertex index
        
        for(i = 0; i < 3; i++)
        {
            vertexs[i].positionCoords.x += movementVectors[i].x;
            if(vertexs[i].positionCoords.x >= 1.0f ||
               vertexs[i].positionCoords.x <= -1.0f)
            {
                movementVectors[i].x = -movementVectors[i].x;
            }
            vertexs[i].positionCoords.y += movementVectors[i].y;
            if(vertexs[i].positionCoords.y >= 1.0f ||
               vertexs[i].positionCoords.y <= -1.0f)
            {
                movementVectors[i].y = -movementVectors[i].y;
            }
            vertexs[i].positionCoords.z += movementVectors[i].z;
            if(vertexs[i].positionCoords.z >= 1.0f ||
               vertexs[i].positionCoords.z <= -1.0f)
            {
                movementVectors[i].z = -movementVectors[i].z;
            }
        }
    }
    else
    {  // Restore the triangle vertex positions to defaults
        int    i;  // by convention, 'i' is current vertex index
        
        for(i = 0; i < 3; i++)
        {
            vertexs[i].positionCoords.x =
            defaultvertexs[i].positionCoords.x;
            vertexs[i].positionCoords.y =
            defaultvertexs[i].positionCoords.y;
            vertexs[i].positionCoords.z =
            defaultvertexs[i].positionCoords.z;
        }
    }
    
    
    {  // Adjust the S texture coordinates to slide texture and
        // reveal effect of texture repeat vs. clamp behavior
        int    i;  // 'i' is current vertex index
        
        for(i = 0; i < 3; i++)
        {
            vertexs[i].textureCoords.s = (defaultvertexs[i].textureCoords.s + sCoordinateOffset);
        }
    }
}


/////////////////////////////////////////////////////////////////
// Called automatically at rate defined by view controller’s
// preferredFramesPerSecond property
- (void)update
{
    return;
    
    [self updateAnimatedVertexPositions];
    [self updateTextureParameters];
    
    [vertexBuffer reinitWithAttribStride:sizeof(sceneVertex)
                        numberOfVertices:sizeof(vertexs) / sizeof(sceneVertex)
                                   bytes:vertexs];
}

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    //clear before draw
    [(AGLKContext *)view.context clear:GL_COLOR_BUFFER_BIT];
    
    [self.vertexBuffer prepareToDrawWithAttrib:GLKVertexAttribPosition
                           numberOfCoordinates:3
                                  attribOffset:offsetof(sceneVertex, positionCoords)
                                  shouldEnable:YES];

//    [self.vertexBuffer prepareToDrawWithAttrib:GLKVertexAttribNormal
//                           numberOfCoordinates:3
//                                  attribOffset:offsetof(sceneVertex, positionCoords2)
//                                  shouldEnable:YES];
    
    [self.vertexBuffer prepareToDrawWithAttrib:GLKVertexAttribTexCoord0
                           numberOfCoordinates:2
                                  attribOffset:offsetof(sceneVertex, textureCoords)
                                  shouldEnable:YES];

    [self.vertexBuffer prepareToDrawWithAttrib:GLKVertexAttribTexCoord1
                           numberOfCoordinates:3
                                  attribOffset:offsetof(sceneVertex, textureCoords)
                                  shouldEnable:YES];

    
    // draw texture 0
    self.baseEffect.texture2d0.name = self.textureInfo0.name;
    self.baseEffect.texture2d0.target = self.textureInfo0.target;
    [self.baseEffect prepareToDraw];
    
    // Draw triangles using the first three vertexs in the
    // currently bound vertex buffer
    [self.vertexBuffer drawArrayWithMode:GL_TRIANGLES
                        startVertexIndex:0
                        numberOfVertices:sizeof(vertexs) / sizeof(sceneVertex)];
    
    // draw texture 1
    [self.vertexBuffer prepareToDrawWithAttrib:GLKVertexAttribPosition
                           numberOfCoordinates:3
                                  attribOffset:offsetof(sceneVertex, positionCoords2)
                                  shouldEnable:YES];
    
    self.baseEffect.texture2d1.name = textureInfo1.name;
    self.baseEffect.texture2d1.target = textureInfo1.target;
    self.baseEffect.texture2d1.envMode = GLKTextureEnvModeDecal;;
    [self.baseEffect prepareToDraw];
    
    // Draw triangles using the first three vertexs in the
    // currently bound vertex buffer
    [self.vertexBuffer drawArrayWithMode:GL_TRIANGLES
                        startVertexIndex:0
                        numberOfVertices:sizeof(vertexs) / sizeof(sceneVertex)];



}

/////////////////////////////////////////////////////////////////
// This method is called by a user interface object configured
// in Xcode and updates the value of the sCoordinateOffset
// property to demonstrate how texture coordinates affect
// texture mapping to geometry
- (IBAction)takeSCoordinateOffsetFrom:(UISlider *)sender
{
    self.sCoordinateOffset = [sender value];
}


/////////////////////////////////////////////////////////////////
// This method is called by a user interface object configured
// in Xcode and updates the value of the shouldRepeatTexture
// property to demonstrate how textures are clamped or repeated
// when mapped to geometry with texture coordinates outside the
// range 0.0 to 1.0.
- (IBAction)takeShouldRepeatTextureFrom:(UISwitch *)sender
{
    self.shouldRepeatTexture = [sender isOn];
}


/////////////////////////////////////////////////////////////////
// This method is called by a user interface object configured
// in Xcode and updates the value of the shouldAnimate
// property to demonstrate how texture coordinates affect
// texture mapping and visual distortion as geometry changes.
- (IBAction)takeShouldAnimateFrom:(UISwitch *)sender
{
    self.shouldAnimate = [sender isOn];
}


/////////////////////////////////////////////////////////////////
// This method is called by a user interface object configured
// in Xcode and updates the value.
- (IBAction)takeShouldUseLinearFilterFrom:(UISwitch *)sender
{
    self.shouldUseLinearFilter = [sender isOn];
}

@end
